#include "CocoLoader.h"
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS
#include <zlib.h>
#else
#include "zlib/zlib.h"
#endif

using namespace std;
using namespace rapidjson;

namespace cocostudio{


char    cTypeName[] = {'N','F','T','O','A','S','V'};
const    char* kTypeNames[] = { "Null", "False", "True", "Object", "Array", "String", "Number" };
const   char* kObjKeyName[] = { "__type" , "classname" };
char    g_Buff[2048];

char*    stExpCocoAttribDesc::GetName(CocoLoader* pCoco)
{
    return ( pCoco->GetMemoryAddr_String() + m_szName );
}

char*    stExpCocoObjectDesc::GetName(CocoLoader* pCoco)
{
    return ( pCoco->GetMemoryAddr_String() + m_szName );
}

int    stExpCocoObjectDesc::GetAttribNum()
{
    return m_cAttribNum;
}

stExpCocoAttribDesc* stExpCocoObjectDesc::GetAttribDescArray(CocoLoader* pCoco)
{
    return (stExpCocoAttribDesc*)( pCoco->GetMemoryAddr_AttribDesc() + m_pAttribDescArray );
}

Type stExpCocoNode::GetType(CocoLoader*    pCoco)
{

    Type    tType = kObjectType;
    if(m_ObjIndex >= 0)
    {
        stExpCocoObjectDesc*    tpCocoObjectDesc = pCoco->GetCocoObjectDescArray() ;
        if( m_AttribIndex >= 0 )
        {
            stExpCocoAttribDesc* tpAttribDescArray = (stExpCocoAttribDesc*) tpCocoObjectDesc[m_ObjIndex].GetAttribDescArray(pCoco);
            tType = Type(tpAttribDescArray[m_AttribIndex].m_cTypeName - 'N' + kNullType);

            if(kFalseType == tType || kTrueType == tType)
            {
                char* szValue = (char*)GetValue(pCoco);
                if(szValue[0] == '0')
                {
                    return kFalseType;
                }
                else
                {
                    return kTrueType;
                }
            }

        }
        else
        {
            tType = kObjectType;
        }
    }
    else
    {
        if(m_AttribIndex >= 0)
        {
            tType   = (Type)m_ChildNum;

            if(kFalseType == tType || kTrueType == tType)
            {
                char* szValue = (char*)GetValue(pCoco);
                if(szValue[0] == '0')
                {
                    return kFalseType;
                }
                else
                {
                    return kTrueType;
                }
            }
        }
        else
        {
            tType = kArrayType;
        }
    }
    return tType;
}

char*    stExpCocoNode::GetName(CocoLoader*        pCoco)
{
    char*   szName  = nullptr ;
    if(m_ObjIndex >= 0)
    {
        stExpCocoObjectDesc*    tpCocoObjectDesc = pCoco->GetCocoObjectDescArray();
        if( m_AttribIndex >= 0 )
        {
            stExpCocoAttribDesc* tpAttribDescArray = (stExpCocoAttribDesc*) tpCocoObjectDesc[m_ObjIndex].GetAttribDescArray(pCoco);
            szName = tpAttribDescArray[m_AttribIndex].GetName(pCoco);
        }
        else
        {
            char* szValue = GetValue(pCoco);
            if(szValue[0])
            {
                szName = GetValue(pCoco);
            }
            else
            {
                szName = tpCocoObjectDesc[m_ObjIndex].GetName(pCoco);
            }
        }
    }
    else
    {
        if(m_AttribIndex >= 0)
        {
            char*   pStringAddr = (char*)pCoco->GetCocoObjectDescArray() + pCoco->GetFileHeader()->m_lStringMemAddr ;
            szName  = m_ChildArray + pStringAddr;
        }
        else
        {
            szName = (char*)GetValue(pCoco);
        }
    }
    return szName ;

}

char* stExpCocoNode::GetValue(CocoLoader* pCoco)
{
    char* szValue = ( pCoco->GetMemoryAddr_String() + m_szValue );
    if( 0==strcmp(szValue,"null") && GetType(pCoco) == kStringType )
    {
        strcpy(szValue,"");
    }
    return szValue;
}


int    stExpCocoNode::GetChildNum()
{
    return m_ChildNum;
}

stExpCocoNode*    stExpCocoNode::GetChildArray(CocoLoader* pCoco)
{
    return (stExpCocoNode*)( pCoco->GetMemoryAddr_CocoNode() + m_ChildArray );
}

CocoLoader::CocoLoader()
{
    m_pRootNode = nullptr;
    m_pObjectDescArray = nullptr;
    m_pMemoryBuff = nullptr;
}

CocoLoader::~CocoLoader()
{
    if(m_pMemoryBuff)
    {
        delete[] m_pMemoryBuff;
        m_pMemoryBuff = nullptr;
    }

}

bool CocoLoader::ReadCocoBinBuff(char* pBinBuff)
{
    if(m_pMemoryBuff)return true;
    char*    pTempBuff = pBinBuff;

    m_pFileHeader = (stCocoFileHeader*)pTempBuff;
    pTempBuff += sizeof(stCocoFileHeader);
    char* pStartAddr = m_pMemoryBuff = pTempBuff;

    char* pDestBuff = new char[m_pFileHeader->m_nDataSize];
    if (m_pFileHeader->m_nCompressSize > 0)
    {
        uLongf        dwSrcSize  = m_pFileHeader->m_nCompressSize;
        uLongf        dwDestSize  = m_pFileHeader->m_nDataSize;
        uncompress((Bytef*)pDestBuff,&dwDestSize,(Bytef*)m_pMemoryBuff,dwSrcSize);
    }
    else
    {
        memcpy(pDestBuff, m_pMemoryBuff, m_pFileHeader->m_nDataSize);
    }
    pStartAddr = m_pMemoryBuff = pDestBuff;

    m_pObjectDescArray = (stExpCocoObjectDesc*)pStartAddr;

    char*    pCocoMemAddr = pStartAddr + m_pFileHeader->m_CocoNodeMemAddr;

    m_pRootNode = (stExpCocoNode*)pCocoMemAddr;

    return true;
}

char*    CocoLoader::GetMemoryAddr_AttribDesc()
{
    return m_pMemoryBuff + m_pFileHeader->m_lAttribMemAddr ;
}

char*    CocoLoader::GetMemoryAddr_CocoNode()
{
    return m_pMemoryBuff + m_pFileHeader->m_CocoNodeMemAddr;
}

char*    CocoLoader::GetMemoryAddr_String()
{
    return m_pMemoryBuff + m_pFileHeader->m_lStringMemAddr ;

}
}

